﻿using BCCommon;
using BCCommon.Extensions;
using BCCommon.OAEnums;
using BCData.OA.Notification.NotificationRecord;
using BCDto.OA.Notification.NotificationRecord;
using BCEntity.OA.Notification.NotificationRecord;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Text;

namespace BCService.OA.Notification.NotificationRecord
{
    public class NotificationRecordService : INotificationRecordService
    {
        private readonly IApplicationContextService applicationContextService;
        private readonly INotificationRecordData notificationRecordData;

        public NotificationRecordService(IApplicationContextService applicationContextService,
            INotificationRecordData notificationRecordData)
        {
            this.applicationContextService = applicationContextService;
            this.notificationRecordData = notificationRecordData;
        }

        public bool Exists(long notificationRecordId)
        {
            return this.notificationRecordData.Exists(notificationRecordId).GetAwaiter().GetResult();
        }

        public NotificationRecordDto Add(NotificationRecordRequestDto requestDto)
        {

            var entity = requestDto.As<NotificationRecordEntity>();

            return this.notificationRecordData.Add(entity).GetAwaiter().GetResult().As<NotificationRecordDto>();
        }
        public bool Add(List<NotificationRecordRequestDto> requestDtos)
        {
            List<NotificationRecordEntity> list = new List<NotificationRecordEntity>();
            foreach (var item in requestDtos)
            {
                var entity = item.As<NotificationRecordEntity>();
                list.Add(entity);
            }
            return this.notificationRecordData.Add(list).GetAwaiter().GetResult();
        }
        public NotificationRecordDto Update(NotificationRecordPutDto putDto)
        {
            if (!this.Exists(putDto.NotificationRecordId))
            {
                throw new ArgumentException("此记录不存在");
            }
            var entity = putDto.As<NotificationRecordEntity>();

            return this.notificationRecordData.Update(entity).GetAwaiter().GetResult().As<NotificationRecordDto>();
        }

        public NotificationRecordDto StartHandleNotification(long notificationRecordId)
        {
            var notificationEntity = this.notificationRecordData.GetEntity(notificationRecordId).GetAwaiter().GetResult();
            if (notificationEntity == null)
            {
                throw new ArgumentException("此记录不存在");
            }

            if (notificationEntity.Status == OAProcessStatus.Processing)
            {
                throw new ArgumentException("此记录他人正在处理中");
            }

            if (notificationEntity.Status == OAProcessStatus.Processed)
            {
                throw new ArgumentException("此记录他人已处理结束");
            }

            if (notificationEntity.Status == OAProcessStatus.Closed)
            {
                throw new ArgumentException("此记录他人已关闭");
            }

            notificationEntity.Status = OAProcessStatus.Processing;
            notificationEntity.ProcessingTime = DateTime.Now;
            notificationEntity.ReceiverId = applicationContextService.Admin.AdminId;
            notificationEntity.ReceiverName = applicationContextService.Admin.FullName;
            this.CalculPercentage(notificationEntity);
            return this.notificationRecordData.Update(notificationEntity).GetAwaiter().GetResult().As<NotificationRecordDto>();
        }

        public NotificationRecordDto HandledNotification(long notificationRecordId)
        {
            var notificationEntity = this.notificationRecordData.GetEntity(notificationRecordId).GetAwaiter().GetResult();
            if (notificationEntity == null)
            {
                throw new ArgumentException("此记录不存在");
            }

            if (notificationEntity.Status == OAProcessStatus.Pending)
            {
                throw new ArgumentException("此记录并无人开始处理，无法完成处理");
            }

            if (notificationEntity.Status == OAProcessStatus.Processed)
            {
                throw new ArgumentException("此记录他人已处理结束");
            }

            if (notificationEntity.Status == OAProcessStatus.Closed)
            {
                throw new ArgumentException("此记录他人已关闭");
            }
            if (!applicationContextService.Admin.IsSystemAccount)
            {
                if (notificationEntity.ReceiverId != applicationContextService.Admin.AdminId)
                {
                    throw new ArgumentException("此记录并非您跟进处理的，请联系跟进处理人完成处理操作");
                }
            }
            notificationEntity.Status = OAProcessStatus.Processed;
            notificationEntity.ProcessedTime = DateTime.Now;
            notificationEntity.ActualEndTime = DateTime.Now;
            this.CalculPercentage(notificationEntity);
            return this.notificationRecordData.Update(notificationEntity).GetAwaiter().GetResult().As<NotificationRecordDto>();
        }

        public NotificationRecordDto CloseNotification(NotificationRecordCloseDto closeDto)
        {
            var notificationEntity = this.notificationRecordData.GetEntity(closeDto.NotificationCategoryCode, closeDto.RelatedReferenceNo).GetAwaiter().GetResult();
            if (notificationEntity == null)
            {
                throw new ArgumentException("此记录不存在");
            }

            if (notificationEntity.Status == OAProcessStatus.Processed)
            {
                throw new ArgumentException("此记录他人已处理结束");
            }

            if (notificationEntity.Status == OAProcessStatus.Closed)
            {
                throw new ArgumentException("此记录他人已关闭");
            }

            notificationEntity.Status = OAProcessStatus.Closed;
            notificationEntity.CloseTime = DateTime.Now;
            notificationEntity.CloseRemark = closeDto.CloseRemark;
            notificationEntity.CloseAdminId = applicationContextService.Admin.AdminId;
            notificationEntity.CloseAdminName = applicationContextService.Admin.FullName;
            this.CalculPercentage(notificationEntity);
            return this.notificationRecordData.Update(notificationEntity).GetAwaiter().GetResult().As<NotificationRecordDto>();
        }

        public bool Delete(long notificationRecordId)
        {
            if (!this.Exists(notificationRecordId))
            {
                throw new ArgumentException("此记录不存在");
            }

            return this.notificationRecordData.Delete(notificationRecordId).GetAwaiter().GetResult();
        }

        public NotificationRecordDto GetEntity(long notificationRecordId)
        {
            var result = this.notificationRecordData.GetEntity(notificationRecordId).GetAwaiter().GetResult();
            this.CalculPercentage(result);
            return result.As<NotificationRecordDto>();
        }

        public PageableList<NotificationRecordDto> Query(OARelatedType relatedType, OAProcessStatus processStatus, DateTime? start, DateTime? end, int pageIndex, int pageSize)
        {
            var (list, count) = this.notificationRecordData.Query(relatedType, processStatus, start, end, pageIndex, pageSize).GetAwaiter().GetResult();

            foreach (var item in list)
            {
                this.CalculPercentage(item);
            }

            return new PageableList<NotificationRecordDto>
            {
                Items = list.TransformTo<NotificationRecordDto>(),
                Count = count,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }

        public IEnumerable<NotificationRecordSumViewDto> GetNotificationList(OARelatedType relatedType, OAProcessStatus processStatus)
        {
            if (!applicationContextService.Admin.DepartmentId.HasValue)
            {
                throw new ArgumentException(string.Format("未设置任何部门，无法获取{0}通知信息", relatedType.GetDescriptionString()));
            }
            var result = this.notificationRecordData.GetNotificationList(relatedType, processStatus, applicationContextService.Admin.CompanyId, applicationContextService.Admin.DepartmentId.Value, applicationContextService.Admin.JobTitleKey, applicationContextService.Admin.AdminId).GetAwaiter().GetResult();

            List<NotificationRecordSumViewDto> list = new List<NotificationRecordSumViewDto>();
            foreach (var item in result)
            {
                this.CalculPercentage(item);
                list.Add(item.As<NotificationRecordSumViewDto>());
            }

            return result.As<IEnumerable<NotificationRecordSumViewDto>>();
        }
        /// <summary>
        /// 计算百分比
        /// </summary>
        /// <param name="notificationEntity">通知信息</param>
        private void CalculPercentage(NotificationRecordEntity notificationEntity)
        {
            if (notificationEntity.Status != OAProcessStatus.Processed && notificationEntity.Status != OAProcessStatus.Closed)
            {
                TimeSpan sourceDiffTimeSpan = notificationEntity.EndTime - notificationEntity.StartTime;
                TimeSpan nowDiffTimeSpan = DateTime.Now - notificationEntity.StartTime;

                var percentage = nowDiffTimeSpan.Hours / sourceDiffTimeSpan.Hours * 100;

                notificationEntity.ProcessBar = percentage;
                notificationEntity.Level = percentage < 30.00 ? OAProcessLevelType.Green : percentage <= 70.00 ? OAProcessLevelType.Yellow : OAProcessLevelType.Red;


                if (notificationEntity.ProcessedTime.HasValue)
                {
                    if (notificationEntity.EndTime < notificationEntity.ProcessedTime.Value)
                    {
                        TimeSpan timeoutDiffTimeSpan = (notificationEntity.ProcessedTime.Value - notificationEntity.EndTime);
                        notificationEntity.Timeout = new DateTime(timeoutDiffTimeSpan.Ticks);
                        notificationEntity.TimeoutSecond = timeoutDiffTimeSpan.Seconds;
                    }
                }
            }
        }

    }
}
